;*******************************************************
; MBR.asm
; selects boot partition and loads boot code from it
;*******************************************************

[ORG 0x7c00]
[BITS 16]

; to properly setup code segment
jmp	0x0000:START

START:
	; start here
	; align segment registers and setup stack at 0x1000
	mov	ax, cs
	mov	ds, ax
	mov	es, ax
	mov	ss, ax
	mov	sp, 0x1000
	
	; relocate code to 0x600
	mov	si, 0x7c00
	mov	di, 0x0600
	mov	cx, 512
	
.relocate_loop:
	mov	al, [si]
	mov	[di], al
	inc	si
	inc	di
	loop	.relocate_loop
	
	; relocation finished
	jmp	0x0000:(0x0600 + 64)
	
;********************************************************
times	64 - ($ - $$) db 0

RELOCATED_START:
	; find bootable partition
	mov	si, 0x0600 + 446
	mov	cx, 4
	
.loop:
	; check for bootable sig
	mov	al, [si]
	and	al, 0x80
	jnz	.bootable
	loop	.loop
	
	; no bootable partition
	mov	si, msgNoBootable - 0x7c00 + 0x0600
	call	PrintString
	cli
	hlt
	
.bootable:
	; ds:si points to boot partition
	; get starting partition sector and save pointer and drive number
	mov	eax, [si + 8]
	push	si
	push	dx
	
LOADSECTORS:
	; load the boot sector at LBA in eax to 0x7c00
	mov	ah, 0		; reset the drive
	int	0x13		; call reset
	mov	[DAPStart - 0x7c00 + 0x0600], eax
	mov	ah, 0x42
	mov	si, DAPSize - 0x7c00 + 0x0600
	int	0x13
	jnc	GOTOBOOTSEC
	mov	si, msgReadError
	call	PrintString
	
GOTOBOOTSEC:
	; restore pointer and drive number
	pop	dx
	pop	si
	
	; togo bootsector
	jmp	0x0000:0x7c00
	
;*******************************
; data

msgNoBootable	db 13,10,"ERROR: No bootable partition found.",0
msgReadError	db 13,10,"ERROR: Could not read from disk.",0

DAPSize		dw 16
DAPCount	dw 1
DAPOffset	dw 0x7c00
DAPSegment	dw 0x0000
DAPStart	dq 0
	
;*******************************
; print a string
; si = pointer to string to print

PrintString:
	; setup registers for video out mode
	mov	ah, 0x0e
	mov	bh, 0x00
	mov	bl, 0x07
	
.loop:	
	; get char
	lodsb		; same as "mov	al, [si] + inc	si"

	; check for nullchar
	or	al, al
	jz	.finish
	
	; if not null, print it & repeat
	int	0x10
	jmp	.loop
	
.finish:
	ret
	
;********************************************************
; partition table goes here
times	446 - ($ - $$) db 0

;********************************************************
; bootsector signature
times	510 - ($ - $$) db 0
dw 0xaa55
